package com.eastcom.collection.tools.common

import org.apache.commons.logging.Log
import javax.jms.Connection;
import javax.jms.ConnectionFactory;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;
import javax.jms.TextMessage;
import javax.naming.Context;
import javax.naming.NamingException;
import javax.naming.directory.InitialDirContext;
public class JmsJndiConfig {
		private String initialContextFactory ;
		private String providerUrl ;
		private String securityAuthentication ;
		private String securityPrincipal ;
		private String securityCredentials ;
		private String referral;
	
		private boolean ready = true;
	
		public JmsJndiConfig() {
	
		}
	
		public void setInitialContextFactory(String initialContextFactory) {
			this.initialContextFactory = initialContextFactory;
		}
	
		public String getInitialContextFactory() {
			return initialContextFactory;
		}
	
		public void setProviderUrl(String providerUrl) {
			this.providerUrl = providerUrl;
		}
	
		public String getProviderUrl() {
			return providerUrl;
		}
	
		public void setSecurityAuthentication(String securityAuthentication) {
			this.securityAuthentication = securityAuthentication;
		}
	
		public String getSecurityAuthentication() {
			return securityAuthentication;
		}
	
		public void setSecurityPrincipal(String securityPrincipal) {
			this.securityPrincipal = securityPrincipal;
		}
	
		public String getSecurityPrincipal() {
			return securityPrincipal;
		}
	
		public void setSecurityCredentials(String securityCredentials) {
			this.securityCredentials = securityCredentials;
		}
	
		public String getSecurityCredentials() {
			return securityCredentials;
		}
	
		public void setReferral(String referral) {
			this.referral = referral;
		}
	
		public String getReferral() {
			return referral;
		}
	
		public void setReady(boolean ready) {
			this.ready = ready;
		}
	
		public boolean isReady() {
			return ready;
		}
	
}
	
public class MQCommunication {
	private Log logger = org.apache.commons.logging.LogFactory.getLog(com.eastcom.groovy.tools.common.MQCommunication.class);
	
	private JmsJndiConfig jmsJndiConfig;
	
	
	private String name = null;
	
	private String factoryName = null;

	private static final int SLEEP_TIME = 60 * 1000; 
	
	private Connection connection;
	
	private Session session;
	
	private Queue queue;
	
	private MessageProducer messageProducer;
	
	private TextMessage message;
	
	private boolean connThread = false;
	
	public Object lockObj = new Object();
	
	public static int count = 0;
	
	public MQCommunication() {
		
	}
	public void init() {
		logger.debug("MQCommunication init...");
		if (!connection()) {
			if(connThread == false) {
				synchronized(lockObj) {
					connThread = true;
				}
				resetConnection();
			}
		}
	}

	public boolean connection() {
		try {
			logger.debug("MQCommunication jmsJndiConfig "+jmsJndiConfig);
			Hashtable<String, String> jndiParameter = new Hashtable<String, String>();
			
			jndiParameter.put(Context.INITIAL_CONTEXT_FACTORY, jmsJndiConfig.getInitialContextFactory());
			jndiParameter.put(Context.PROVIDER_URL, jmsJndiConfig.getProviderUrl());
			jndiParameter.put(Context.SECURITY_AUTHENTICATION, jmsJndiConfig.getSecurityAuthentication());
			jndiParameter.put(Context.SECURITY_PRINCIPAL, jmsJndiConfig.getSecurityPrincipal());
			jndiParameter.put(Context.SECURITY_CREDENTIALS, jmsJndiConfig.getSecurityCredentials());
			jndiParameter.put(Context.REFERRAL, "throw");
			logger.debug("MQCommunication connection :"+name+"|"+factoryName+"|"+jmsJndiConfig.getInitialContextFactory()+"|"+jmsJndiConfig.getProviderUrl()+"|"+jmsJndiConfig.getSecurityAuthentication()+"|"+jmsJndiConfig.getSecurityPrincipal()+"|"+jmsJndiConfig.getSecurityCredentials());
			
			Context jndiContext = new InitialDirContext(jndiParameter);
			println jndiContext
    		ConnectionFactory connectionFactory = (ConnectionFactory) jndiContext.lookup(factoryName);
			println connectionFactory
			queue = (Queue) jndiContext.lookup(name);
			println queue
			jndiContext.close();
			
			connection = connectionFactory.createConnection();
			connection.start();
			logger.debug("MQCommunication connection "+connection);
			session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
			messageProducer = session.createProducer((Destination) queue);
		} catch(NamingException e) {
			if(connThread == false) {
				synchronized(lockObj) {
					connThread = true;
				}
				e.printStackTrace();
				logger.error("NamingException:"+e.getMessage(), e);
				resetConnection();
			}
			return false;
		} catch(JMSException e) {
			if(connThread == false) {
				synchronized(lockObj) {
					connThread = true;
				}
				e.printStackTrace();
				logger.error("JMSException:"+e.getMessage(), e);
				resetConnection();
			}
			return false;
		}
		logger.debug("DA connection QM_FM over");
		return true;
	}
	
	private void resetConnection() {
		Thread resetThread = new Thread("ResetConnectMQThread") {
			public void run() {
				logger.debug("Reset Connection MQ Thread start");
				MQCommunication mqConnector = com.eastcom.groovy.provider.SpringContextProvider.getBean("mqConnector")
				mqConnector.disConnection();
				while(!mqConnector.connection()) {
					try { Thread.sleep(SLEEP_TIME); } catch(InterruptedException e) {}
					logger.debug("Reset Connection MQ Thread sleep " + SLEEP_TIME/1000 + " SEC");
				}
				synchronized(lockObj) {
					connThread = false;
				}
				logger.debug("Reset Connection MQ Thread stopped");
			}
		};
		resetThread.start();
	}

	public void disConnection() {
		try {
			if(session != null) {
				session.close();
				session = null;
			}
			if(connection != null) {
				connection.close();
				connection = null;
			}
		} catch(JMSException e) {
		}
	}
	
	public boolean sendMessage(String msg) {
		try {
			message = session.createTextMessage(msg);
			message.setIntProperty ("MessageID", count);
			synchronized(lockObj) {
				if (count >= 65535)
					count = 0;
				else
					count++;
			}
			
			messageProducer.send(message);
			logger.debug("send alarm message[JMS][cumulate send number : " + count + "] : " + msg);
			return true;
		} catch(JMSException e) {
			if(e.getLinkedException().getMessage().trim().endsWith("2053")) {
				logger.error("sendMessage exception : MQ Full , send failure [" + msg + "]");
				return false;
			}
		}
		logger.debug("send alarm message[JMS] failure : " + msg);
		if(connThread == false) {
			synchronized(lockObj) {
				connThread = true;
			}
			resetConnection();
		}
		return false;
	}
//	
//	public void sendNhmAlarm(String objectId, String eventId, String info) throws IOException {
//		String foundObjectId = objectId;
//
//        CacheItem item = getEvent(foundObjectId, eventId);
//        if (item == null) {
//            logger.debug("Send Fail Because Invalid EventId : " + eventId);
//            return;
//        }
//        String key = item.getKey();
//        //第一次不管什么级别全发，是为了在cache里放这个设备的告警信息
//        if (!fmCacheTable.getCacheTables().containsKey(key)) {
//        	fmCacheTable.putCacheItem(key, item);
//            send(objectId, eventId, info);
//        } else {
//        	//以后会判断，如果是ERROR就直接发。如果是INFO，需要和上次的结果做对比。上次也是info，就不发了，也就是发告警有3种可能，1：设备第一次采集  2：ERROR级别 3:对告（上次是ERROR，本次是INFO，需要对冲）
//            CacheItem old = fmCacheTable.getCacheItem(key);
//            if (item.getSev().equals("INFO")) {
//                if (!old.getSev().equals("INFO")) {
//                    old.setSev(item.getSev());
//                    send(objectId, eventId, info);
//                }
//            } else {
//                old.setSev(item.getSev());
//                send(objectId, eventId, info);
//            }
//        }
//	}
//	
//	private CacheItem getEvent(String objectId, String eventId) throws IOException {
//        int ind1, ind2;
//        ind1 = eventId.indexOf("-");
//        ind2 = eventId.lastIndexOf("-");
//        if (ind1 == -1 || ind2 == -1) {
//        	 logger.debug("invalid eventId : " + eventId);
//            return null;
//        }
//        String tmp0 = eventId.substring(0, ind1);
//        String tmp1 = eventId.substring(ind1 + 1, ind2);
//        String tmp2 = eventId.substring(ind2 + 1);
//
//        String eventHead = new String(tmp0 + "-" + tmp2);
//        String severity = tmp1;
//
//        CacheItem item = new CacheItem();
//        item.setEventHead(eventHead);
//        item.setId(objectId);
//        item.setSev(severity);
//
//        return item;
//    }
	
	private void send(String objId, String eventid, String info) throws IOException {
		logger.debug("send alarm message : " + info);
		sendMessage(info);
		
	}

	public String getFactoryName() {
		return factoryName;
	}

	public void setFactoryName(String factoryName) {
		this.factoryName = factoryName;
	}

	public JmsJndiConfig getJmsJndiConfig() {
		return jmsJndiConfig;
	}

	public void setJmsJndiConfig(JmsJndiConfig jmsJndiConfig) {
		this.jmsJndiConfig = jmsJndiConfig;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
	@Override
	public String toString() {
		return "MQCommunication [logger=" + logger + ", jmsJndiConfig="
				+ jmsJndiConfig + ", name=" + name + ", factoryName="
				+ factoryName + ", connection=" + connection + ", session="
				+ session + ", queue=" + queue + ", messageProducer="
				+ messageProducer + ", message=" + message + ", connThread="
				+ connThread + ", lockObj=" + lockObj + "]";
	}
}
